//
//  DSlider.swift
//  DSP
//
//  Created by tucici on 2024/5/16.
//

import UIKit
import TCCKit
enum DSliderDirection{
    case vertical
    case horizontal
}

@objc protocol DSliderDelgate {
    func valueForChange(_ sender:DSlider)
    @objc optional func valueForChangeEnd(_ sender:DSlider)
    @objc optional func actionForInterval(_ sender:DSlider,  _ time:Double)
}
private var _temp_value : CGFloat = 0.0
class DSlider: UIView {
    var delegate : DSliderDelgate?
    var minValue : CGFloat = 0.0
    var maxValue : CGFloat = 1.0
    var currentValue : CGFloat = 0.0{
        didSet{
            animateBarHeight(currentValue)
        }
    }
    var thumImg : UIImageView!
    private var shapeView : UIView!
    private var shape : CAShapeLayer!
    private var colorLayer : CAGradientLayer!
    private var didAnimation = false
    private var displayLink: CADisplayLink?
    ///因为在<'valueForChange'>和<'valueForChangeEnd'>两个方法里，如果做一些数据上传，
    ///明显不合适，一个滑动会调用很多次，一个只有滑动结束才调用。
    ///每间隔多长时间，调用一次actionForInterval，均匀的通过actionForInterval实现数据上传
    private var interval : Double = 0.5
    private var timer = DispatchSource.makeTimerSource(queue:.main)
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        initUI()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func initUI(){
        translatesAutoresizingMaskIntoConstraints = false
        
        timer.setEventHandler(handler:{[weak self] in
            if let self = self {
                self.delegate?.actionForInterval?(self, self.interval)
             }
        })
        timer.schedule(deadline: .now(), repeating: interval)
        
        thumImg = UIImageView()
        thumImg.contentMode = .scaleAspectFill
        
        shape = CAShapeLayer()
        // shape.fillColor = UIColor.clear.cgColor
        shape.fillColor = HEX_BLUE.color().cgColor
        
        colorLayer = CAGradientLayer()
        colorLayer.colors = [HEX_RED.color().cgColor, HEX_RED.color().cgColor]
        
        shapeView = UIView()
        shapeView.backgroundColor = .clear
        shapeView.isUserInteractionEnabled = false
        enable = true
        
        addSubview(shapeView)
        shapeView.layer.addSublayer(shape)
        shapeView.layer.addSublayer(colorLayer)
        shapeView.addSubview(thumImg)
        ///！！！！！这里一定要注意，要放在<shapeView.layer.addSublayer(colorLayer)>后面 ，否则colorLayer不会跟着shape形变
        colorLayer.mask = shape
        
        
        let pan2 = UIPanGestureRecognizer(target:self, action:#selector(actionForPan))
        self.addGestureRecognizer(pan2)
        direction = .vertical
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        if didAnimation {return}
        animateBarHeight(currentValue)
    }
    
    func setColors(_ colors:[UIColor]){
        CATransaction.begin()
        CATransaction.setDisableActions(true)
        colorLayer.colors = colors.map{$0.cgColor}
        CATransaction.commit()
    }
    
    var direction : DSliderDirection = .vertical{
        didSet{
            switch direction{
            case .vertical:
                colorLayer.locations = [0,1]
                colorLayer.startPoint = CGPoint(x: 0, y: 0)
                colorLayer.endPoint = CGPoint(x: 1, y: 0)
                thumImg.snp.remakeConstraints { make in
                    make.width.equalTo(thumImg.snp.height)
                    make.top.bottom.equalToSuperview().inset(0)
                    make.left.equalToSuperview().offset(0)
                }
                shapeView.cornerRadius = 5.k_h
                shapeView.snp.remakeConstraints { make in
                    make.left.right.equalToSuperview().inset(5.k_w)
                    make.height.equalTo(10.k_h)
                    make.centerY.equalToSuperview()
                }
                thumImg.layoutIfNeeded()
            case .horizontal:
                colorLayer.locations = [0,1]
                colorLayer.startPoint = CGPoint(x: 0, y: 1)
                colorLayer.endPoint = CGPoint(x: 0, y: 0)
                thumImg.snp.remakeConstraints { make in
                    make.width.equalTo(thumImg.snp.height)
                    make.left.right.equalToSuperview().inset(0)
                    make.bottom.equalToSuperview().offset(0)
                }
                shapeView.cornerRadius = 5.k_w
                shapeView.snp.remakeConstraints { make in
                    make.top.bottom.equalToSuperview().inset(5.k_h)
                    make.width.equalTo(10.k_w)
                    make.centerX.equalToSuperview()
                }
                thumImg.layoutIfNeeded()
            }
        }
    }
    
    var enable:Bool = true{
        didSet{
            shapeView.borderWidth = enable ? 1 : 0.5
            shapeView.borderHexColor = enable ? HEX_BLACK : HEX_BORDER_DISABLE
            shapeView.bgHexColor = enable ? HEX_BG : HEX_BG_DISABLE
            setColors(enable ? [HEX_RED.color(), HEX_RED.color()] : [HEX_GRAY2.color(),HEX_GRAY2.color()])
            isUserInteractionEnabled = enable
        }
    }
    
    @objc private func actionForPan(_ pan:UIPanGestureRecognizer){
        let location = pan.location(in: shapeView)
        let locationX = min(max(0, location.x), shapeView.bounds.width)
        let locationY = min(max(0, location.y), shapeView.bounds.height)
        let x = (locationX) / shapeView.bounds.width * (maxValue - minValue)
        let y = (shapeView.bounds.height - locationY) / shapeView.bounds.height * (maxValue - minValue)
        ///这个算法非常重要，可保证(min...max = -10...0) , (min...max = -10...10) ,(min...max = 0...10) 三种情况下，currentVaue都是正确的
        _temp_value = minValue + (direction == .vertical ? x : y)
        if pan.state == .ended{
            displayLink?.invalidate()
            displayLink = nil
            timer.suspend()
            currentValue = _temp_value
            DispatchQueue.main.async {[weak self] in
                self?.delegate?.valueForChangeEnd?(self ?? DSlider())
            }
        }else if pan.state == .began{
            displayLink = CADisplayLink(target: self, selector: #selector(handleDisplayLink))
            displayLink?.add(to: .main, forMode: .common)
            timer.resume()
        }
    }
    
    @objc private func handleDisplayLink() {
        DispatchQueue.main.async {[weak self] in
            self?.delegate?.valueForChange(self ?? DSlider())
        }
        currentValue = _temp_value
    }
    
    private func animateBarHeight(_ value:CGFloat) {
        didAnimation = shapeView.bounds.width > 0
        colorLayer.frame = shapeView.bounds
        shape.frame = shapeView.bounds
        ///因为max和min可能为负数，所以归一 化
        let scale = CGFloat(value - minValue) / CGFloat(maxValue - minValue)
        var oldPath : UIBezierPath!
        var newPath : UIBezierPath!
        switch direction {
        case .vertical:
            let offsetX = shape.bounds.width * scale
            newPath = UIBezierPath(roundedRect:CGRect(x:0, y:0,
                                                      width:offsetX + thumImg.bounds.width / 2.0, height:shape.frame.height),
                                   byRoundingCorners:[.topLeft,.topRight,.bottomLeft,.bottomRight],
                                   cornerRadii:CGSize(width:shape.bounds.height/2.0, height: shape.bounds.height/2.0))
            
            oldPath = UIBezierPath(roundedRect:CGRect(x:0, y: 0,
                                                      width:shape.bounds.width, height: shape.bounds.height),
                                   byRoundingCorners:[.topLeft,.topRight,.bottomLeft,.bottomRight],
                                   cornerRadii:CGSize(width:shape.bounds.height/2.0, height:shape.bounds.height/2.0))
            thumImg.snp.updateConstraints { make in
                make.left.equalToSuperview().offset(min(offsetX, shapeView.bounds.width-thumImg.bounds.width))
            }
        case .horizontal:///竖直状态下，y轴滑动位移，下->上 = 小->大。而UIBezierPath画线的顶点的Y轴是，上->下 = 小->大。就不能直接使用上面的逻辑。
            let offsetY = (shape.bounds.height - thumImg.bounds.height) * scale
            let y = offsetY + thumImg.bounds.width / 2.0///实际上有用的滑动的点是thumimg的中心
            newPath = UIBezierPath(roundedRect:CGRect(x:0, y:shape.bounds.height-y,
                                                      width:shape.frame.width, height:y),
                                   byRoundingCorners:[.topLeft,.topRight,.bottomLeft,.bottomRight],
                                   cornerRadii:CGSize(width:shape.bounds.width/2, height: shape.bounds.width/2))
            
            oldPath = UIBezierPath(roundedRect:CGRect(x:0, y: shape.bounds.height,
                                                      width:shape.bounds.width, height: 0),
                                   byRoundingCorners:[.topLeft,.topRight,.bottomLeft,.bottomRight],
                                   cornerRadii:CGSize(width:shape.bounds.width/2, height:shape.bounds.width/2))
            thumImg.snp.updateConstraints { make in
                make.bottom.equalToSuperview().offset(max(-offsetY, thumImg.bounds.height - shape.bounds.height))
            }
        }
        
        let animation = CABasicAnimation(keyPath: "path")
        animation.fromValue = oldPath.cgPath
        animation.toValue = newPath.cgPath
        animation.duration = 0.001 // 动画持续时间，可以根据需要进行调整
        animation.fillMode = .forwards
        animation.isRemovedOnCompletion = false
        shape.removeAnimation(forKey: "pathAnimation")
        shape.add(animation, forKey: "pathAnimation")
    }
}


